package workflow

import (
	"fmt"
	"product/common/toolbox"
	"product/common/validator"
	"strconv"
)

// NewDag 实例化一个DAG
func NewDag() *Dag {
	return &Dag{
		NodeMap:       make(map[string]*DagNode),
		ID:            "0",
		hasForwarding: true,
	}
}

// AddNode 添加节点
// 节点ID不能重复
func (dag *Dag) AddNode(dg *Dag) error {
	for nodeId, node := range dg.NodeMap {
		_, duplicate := dag.NodeMap[nodeId]
		if duplicate {
			return fmt.Errorf("%s", ErrReplicateNode)
		}
		dag.NodeMap[nodeId] = node
	}
	return nil
}

// AddVertex 添加顶点
// 顶点ID不能重复
func (dag *Dag) AddVertex(id string, operations []IOperation) *DagNode {
	rootNode := &DagNode{
		ID:         id,
		operations: operations,
		forwarder:  make(map[string]ForwarderType),
		parentDag:  dag,
	}
	dag.nodeIndex++
	dag.NodeMap[id] = rootNode
	return rootNode
}

// GetNode 获取节点
// 节点ID必须存在
func (dag *Dag) GetNode(id string) *DagNode {
	return dag.NodeMap[id]
}

// GetParentNode 获取父节点
func (dag *Dag) GetParentNode() *DagNode {
	return dag.ParentNode
}

// GetStartNode 获取开始节点
func (dag *Dag) GetStartNode() *DagNode {
	return dag.startNode
}

// GetEndNode 获取结束节点
func (dag *Dag) GetEndNode() *DagNode {
	return dag.endNode
}

// HasBranch 是否有分支
func (dag *Dag) HasBranch() bool {
	return dag.hasBranch
}

// HasEdge 是否有边
func (dag *Dag) HasEdge() bool {
	return dag.hasEdge
}

func (dag *Dag) GetDynamicNodes(dynamicOption string) []string {
	var nodes []string
	for _, b := range dag.NodeMap {
		dynamicNodeId := strconv.FormatInt(toolbox.GetUniqueId(), 10)
		if !validator.IsEmptyString(dynamicOption) {
			dynamicNodeId = dynamicNodeId + "_" + dynamicOption
		}
		nodes = append(nodes, dynamicNodeId)
		// 是否包含动态子Dag
		if b.isDynamic {
			continue
		}
		if b.subDag != nil {
			subDagNodes := b.subDag.GetDynamicNodes(dynamicOption)
			nodes = append(nodes, subDagNodes...)
		}
	}
	return nodes
}

// IsForwardingData 检查是否有中转数据
func (dag *Dag) IsForwardingData() bool {
	return dag.hasForwarding
}

//// AddEdge 添加边界
//func (dag *Dag) AddEdge(from, to string) error {
//	var fromNode *DagNode
//	var toNode *DagNode
//	if !maps.IsExistsKey(dag.NodeMap, from) {
//		fromNode = dag.AddVertex(from, []IOperation{})
//	}
//	if !maps.IsExistsKey(dag.NodeMap, to) {
//		toNode = dag.AddVertex(to, []IOperation{})
//	}
//}
